<script setup lang="ts">
import type InputProps from "./type/InputProps.ts";
import type InputEmits from "./type/InputEmits.ts";
import {useInput} from "@/components/input/composable/useInput.ts"

const $emit = defineEmits<InputEmits>()

const $prop = withDefaults(defineProps<InputProps>(), {
  labelPlacement: "left",
  type: "text",
  pageSize: "medium",
  disabled: false,
  width: "100%",
  required: false,
  borderColor: "#1c7bfb",
  margin: 4,
  rules: () => [] as ((val: string) => true | string)[],
  allows: () => [] as ((val: string) => boolean)[],

  min: 0,
  max: Number.MAX_VALUE,
  step: 1
})

const {
  labelWidth,
  displayValue,
  numberInputRef,
  height,
  lightBorderColor,
  errorMessage,
  showPassword,
  commonAttrs,
  formFieldExposed,
  focused,
  plus,
  minus,
  cleanInput,
} = useInput($prop, $emit)

// 暴露给父组件使用（ref 调用）
defineExpose(formFieldExposed)

</script>

<template>
  <div class="input-container" :class="`label-${$prop.labelPlacement}`">
    <label v-if="label" class="input-label">
      <span>{{ label }}</span>
      <span v-if="required" style="color: #d03050">&nbsp;*</span>
      <span v-else style="visibility: hidden">&nbsp;*</span>
    </label>
    <div class="input-wrapper" :class="{ disabled, error: !!errorMessage, focused }">
      <!-- 前置插槽 -->
      <slot name="prefix"/>

      <!-- 文本域 -->
      <template v-if="type === 'textarea'">
        <textarea class="input" :value="displayValue" style="width: 100%; resize: vertical;" v-bind="commonAttrs"/>
      </template>

      <!-- 密码 -->
      <template v-else-if="type === 'password'">
        <input class="input" :type="showPassword ? 'text': 'password'" :value="displayValue" v-bind="commonAttrs">
      </template>

      <!-- 数字 -->
      <template v-else-if="type === 'number'">
        <input ref="numberInputRef" class="input" type="text"
               :value="displayValue" v-bind="commonAttrs">
      </template>

      <!-- 普通文本 -->
      <template v-else>
        <input ref="textInputRef" class="input" type="text" :value="displayValue" v-bind="commonAttrs">
      </template>

      <!-- 清空数据 -->
      <template v-if="clearable && modelValue">
        <component is="x-circle" class="clearable-icon" @mousedown.prevent="cleanInput"/>
      </template>

      <!-- 数字输入框的plus和minus按钮 -->
      <template v-if="type === 'number'">
        <!-- plus -->
        <component class="number-plus-minus-icon" is="plus" @click="plus" @pointerdown.prevent/>
        <!-- sub -->
        <component class="number-plus-minus-icon" is="minus" @click="minus" @pointerdown.prevent/>
      </template>

      <!-- 密码输入框的eye按钮 -->
      <template v-if="type === 'password'">
        <component
            :is="showPassword ? 'eye-close' : 'eye-open'"
            :class="showPassword ? 'password-eye-close-icon': 'password-eye-open-icon'"
            @mousedown="showPassword = true"
            @mouseup="showPassword = false"
            @mouseleave="showPassword = false"
        />
      </template>

      <!-- 后置插槽 -->
      <slot name="suffix"/>

      <!-- 校验失败的提示文字 -->
      <div v-if="errorMessage" class="error-message">{{ errorMessage }}</div>
    </div>
  </div>
</template>

<style scoped>
.input-container {
  display: flex;
  align-items: center;
  font-size: 14px;
  margin: v-bind(margin+ "px");
  gap: 3px;
}

.input-label {
  width: v-bind(labelWidth+ "px");
  white-space: nowrap;
}

.label-left {
  flex-direction: row;
  align-items: center;
}

.label-left .input-label {
  text-align: right;
}

.label-top {
  flex-direction: column;
  align-items: flex-start;
}

.label-right {
  flex-direction: row-reverse;
  align-items: center;
}

.label-right .input-label {
  text-align: left;
  padding-left: 3px;
}

.label-bottom {
  flex-direction: column-reverse;
  align-items: flex-start;
}

.input-wrapper {
  position: relative;
  width: calc(100% - v-bind(labelWidth+ "px"));
  padding-right: 5px;
  display: flex;
  align-items: center;
  border: 1px #e0e0e6 solid;
  border-radius: 2px;
  transition: all .3s ease;
  gap: 3px;
  box-sizing: border-box;
  background-color: white;
  box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.08), inset -1px -1px 1px rgba(255, 255, 255, 0.6);
}

.input-wrapper.disabled .input {
  cursor: not-allowed;
  opacity: 0.5;
  filter: grayscale(0.3);
}

.input-wrapper.focused .input {
  caret-color: v-bind(borderColor);
}

.input-wrapper:hover:not(.disabled) {
  border-color: v-bind(borderColor);
}

.input-wrapper.focused:not(.disabled) {
  border: 1px solid v-bind(borderColor);
  box-shadow: 0 0 0 2px v-bind(lightBorderColor);
}

.input {
  width: 100%;
  height: v-bind(height);
  box-sizing: border-box;
  padding: 0 3px;
}

/*校验失败的提示文字*/
.input-wrapper.error {
  border: 1px #ff4d4f solid;
}

.error-message {
  position: absolute;
  top: 100%;
  left: 0;

  color: #ff4d4f;
  font-size: 12px;
  margin-top: 4px;
  line-height: 1em;
  white-space: nowrap;
}

.label-bottom .error-message {
  top: calc(50% - 12px);
  left: 100%;
}

/**
 * 输入框图标的样式
 */
.clearable-icon {
  color: #929292;
  cursor: pointer;
  user-select: none;
  transition: color .3s ease;
}

.clearable-icon:hover {
  color: v-bind(borderColor);
}

.number-plus-minus-icon {
  cursor: pointer;
  user-select: none;
  transition: color .3s ease;
}

.number-plus-minus-icon:hover {
  color: v-bind(borderColor);
}

.password-eye-open-icon {
  cursor: pointer;
  user-select: none;
  transition: color .3s ease;
}

.password-eye-close-icon {
  color: v-bind(borderColor);
  cursor: pointer;
  user-select: none;
}

.password-eye-open-icon:hover {
  color: v-bind(borderColor);
}
</style>